perm filename NDEBUG.SCM[SCH,LSP] blob sn#688838 filedate 1982-11-14 generic text, type T, neo UTF8
;;;-*-SCHEME-*-

;;;;  Top level variable so debugger is always available (even if loaded
;;;  during error)

(eval 

'(define debugger-package
  (make-environment


(define-export exit system-global-environment nil)


;;;Read-execute-print loop for a set of commands associated with functions

(define (letter-commands commands prompt)

  (define (inner-loop val)
    (if (eq? val *noprint*) nil
	(print val))
    (newline)
    (let ((input (readch prompt)))
      (let ((func (or (assq input commands)
		      (assq (char (- (ascii input) 32.)) commands))))
	(if (null? func)
	    (inner-loop *noprint*)
	    (inner-loop ((cdr func)))))))

  (define (driver-loop)
    (catch exit
	   (let ((abort-message
		  (catch again
			 (fluid-let ((abort-to-previous-driver
				      abort-to-nearest-driver)
				     (return-to-caller-of-driver exit)
				     (abort-to-nearest-driver again))
				    (inner-loop *noprint*)))))
	     (display abort-message " Returning to lazy" "loop.")
	     (driver-loop))))
  (driver-loop))

;;;;Environment manipulation package

(define env-package
  (make-environment
   
   (define env nil)
   (define current-frame nil)

   
   ;;; Lexpr since it can take one or no arguments
   
   (define-export (where . possible-env) system-global-environment
     (loop (if (null? possible-env)
	       (the-read-eval-print-environment)
	       (car possible-env))))
   

   (define (loop environment)
     (newline)
     (set! env environment)
     (set! current-frame environment)
     (letter-commands env-commands "Where--> "))


   (define (enter-environment env)
     (read-eval-print env
		      "You are now in the desired environment"
		      "Eval-in-env--> "))
        
   
   (define (show)
     (show-frame current-frame))
   
   (define (show-all)
     (define (s1 env)
       (if (eq? system-global-environment env) *noprint*
	   (sequence
	    (show-frame env)
	    (s1 (frame-parent env)))))
     (s1 env))

   (define (show-frame frame)
     (if (eq? system-global-environment frame)
	 (display "This frame is the global environment")
	 (print (frame-bindings frame)))
     (newline))


  (define (parent)
    (if (eq? system-global-environment parent)
	(display
	 "The current frame is the global environment, it has no parent")
	(sequence
	 (set! current-frame (frame-parent current-frame))
	 (show))))

  (define (son)
    (define (son-1 prev next)
      (if (eq? next current-frame)
	  (set! current-frame prev)
	  (son-1 next (frame-parent next))))
    (if (eq? current-frame env)
	(display "This frame has no offspring")
	(son-1 env (frame-parent env)))
    (show))

  (define (enter) (enter-environment current-frame))
  
  (define (help)
    (display
"
E    Create a read-eval-print loop in the current environment
S    Find the son of the current environment in the current chain
P    Find the parent frame of the current one
H    Display the bindings in the current frame
A    Display the bindings of all the frames in the current chain
Q    Exit
?    Help, print this cruft"))


  (define (exit)
    (return-to-caller-of-driver *noprint*))

  (define env-commands
    (list `(E ,@enter)
	  `(S ,@son)
	  `(P ,@parent)
          `(H ,@show)
	  `(A ,@show-all)
	  `(Q ,@exit)
	  `(? ,@help)))))
  

;;;;History part of the debugger


(define history-package
  (make-environment

   ;;; "State" variables

   (define history nil)
   (define caller nil)
   (define error-info nil)


   (define spine-levels 0)
   (define rib-levels 0)

   (define current-height 0)
   (define current-width 0)

   (define current-reductions nil)
   (define current-branches nil)
   (define current-reduction nil)
   (define $ nil)

   (define toggle nil)
   (define *exit* '(*exit*))
   (define *change-mode* '(*change-mode*))

   ;;; Manipulators:


   (define (rib-reductions rib) (car rib))

   (define (rib-subexpressions rib) (cadr rib))

   
   (define (branch-expression branch) (car branch))

   (define (branch-value branch) (cadr branch))


   (define (reduction-procedure reduction)
     (frame-procedure (cadr reduction)))

   (define (reduction-arguments reduction)
     (frame-arguments (cadr reduction)))

   (define (reduction-environment reduction)
     (cadr reduction))

   (define (reduction-expression reduction)
     (car reduction))

   
   ;;;;Initialization and loops for both modes

   (define-export (debug . flag) system-global-environment
     (set! history (the-saved-history))
     (set! caller return-to-caller-of-driver)
     (if history
	 (sequence
	  (set! error-info
		(let ((original (car the-read-eval-print-messages)))
		  (cons "Message:"
			(if (symbol? original)
			    (list original)
			    original))))
	  (set! spine-levels (-1+ (length history)))
	  (move 0 0 "There is no history saved at all!" nil)
	  (if (memq (reduction-procedure current-reduction)
		    (list error bkpt))
	      (sequence
	       (set!-car current-reductions (cadr current-reductions))
	       (set!-cdr current-reductions (cddr current-reductions))
	       (set!-car (cdar history) '(foo))
	       (move 0 0 "There is no history saved at all!" nil)))
	  (if (and flag (car flag)) (reduction) (all-history))
	  (mode))
	 (display "There is no history saved at all!")))


   (define (lazy-mode)
     (let ((val (letter-commands hist-commands
				 "Lazy-debug--> ")))
       (if (eq? val *exit*)
	   *noprint*
	   (sequence (set! mode normal-mode)
		     (normal-mode)))))

   
   (define (normal-mode)
     (fluid-let ((exit return-to-caller-of-driver))
	(catch toggle-mode
	       (sequence
		(set! toggle toggle-mode)
		(read-eval-print history-package
				 "You are in debugger command mode"
				 "Debugger-command--> "))))
     (set! mode lazy-mode)
     (lazy-mode))

     
   ;;;; Commands

   ;;;Environments:
   
   (define (debug-where)                        ;command W
     (where
      (reduction-environment current-reduction)))

   (define (enter)                              ;command E
     ((access enter-environment env-package)
      (reduction-environment current-reduction)))

   (define (eval-in-current-environment)        ;command V
     (newline)
     (eval (read "Eval--> ")
	   (reduction-environment current-reduction)))

   (define (procedure)
     (reduction-procedure current-reduction))

   (define (environment)
     (reduction-environment current-reduction))

   
   ;;;Proceeding:
   
   (define (return-lazy)                        ;command R
     (newline)
     (let ((inp (read "Exp to proceed with: -> ")))
       (newline)
       (if (read "Confirm: [T or NIL] -> ")
	   (return (if (eq? inp '$) $ inp))
	   *noprint*)))


;;; FIX DYNAMIC THROW TO FORCE VALUE OF DELAYS WHICH GO THROUGH IT.

   (define (return exp)
     (let ((val (eval exp	;EVALUATION SHOULD HAPPEN AFTER THROW!
		      (reduction-environment current-reduction)))
	   (appropriate-caller (find-caller current-height caller)))
       (merge-history current-height)
       (appropriate-caller val)))

   (define find-caller (get-lisp-procedure 'find-caller))

   ;;;Displaying:

   (define (all-history)                        ;command H
     (display-history history 0))

   (define (display-history left level)
     (cond ((null? left) *noprint*)
	   ((eq? left 'wrap-around)
	    (display "Wrap around in history!")
	    (newline))
	   (else
	    (display-rib (rib-reductions (car left)) 0 level)
	    (display-history (cdr left) (1+ level)))))


   (define (all-reductions)                     ;command A
     (display-rib current-reductions 0 current-height))

   (define (display-rib rib wi he)
     (cond ((null? rib) *noprint*)
	   ((eq? rib 'wrap-around)
	    (display "Wrap around in the reductions at this level!")
	    (newline))
	   ((and (= he spine-levels)
		 (eq? (reduction-procedure (car rib))
		      eval))
	    *noprint*)
	   (else
	    (display-reduction (car rib) he wi)
	    (display-rib (cdr rib) (1+ wi) he))))

   
   (define (reduction)                          ;command S
     (newline)
     (display-reduction current-reduction current-height current-width))
   
   (define (display-reduction reduction he wi)
     (fluid-let ((*print-depth* 5)
		 (*print-breadth* 5))
       (display "Subproblem level:" he " Reduction number:" wi)
       (display "Expression" (unsyntax (reduction-expression reduction)))
       (display "Within procedure" (reduction-procedure reduction)
		"applied to" (reduction-arguments reduction))
       (newline)))


   (define (subexpressions)                     ;command X
     (display-branches current-branches))
   
   (define (display-branches branches)
     (cond ((null? branches) *noprint*)
	   ((eq? branches 'wrap-around)
	    (display "Wrap around in the subexpressions at this level!")
	    (newline))
	   (else
	    (fluid-let ((*print-depth* 5)
			(*print-breadth* 5))
	      (display "Subexpression:"
		       (unsyntax (branch-expression (car branches)))
		       " value:" (branch-value (car branches)))
	      (newline))
	    (display-branches (cdr branches)))))



   (define (print-procedure)                    ;command P
     (pp (reduction-procedure current-reduction)))



   ;;;Motion:
   
   (define (previous-subproblem)                ;command D
     (move (1+ current-height) 0
	   "You are already at the first subproblem level"
	   t))
   
   (define (next-subproblem)                    ;command U
     (move (-1+ current-height) 0
	   "You are already at the last subproblem level"
	   t))
   
   (define (next-reduction)                     ;command F
     (h-move (-1+ current-width)
	     "You are already at the last reduction at this level"
	     t))

   (define (previous-reduction)                 ;command B
     (h-move (1+ current-width)
	     "You are already at the first reduction at this level"
	     t))

   (define (go-lazy)                            ;command G
     (newline)
     (select-subproblem-loop)
     (select-reduction-loop)
     (reduction))

   (define (select-subproblem-loop)
     (princ "Subproblem level (0 to ")
     (princ spine-levels)
     (cond ((null? (select-subproblem (read ") --> ")))
	    (display "That subproblem doesn't exist")
	    (select-subproblem-loop))
	   (else
	    *noprint*)))

   (define (select-subproblem height)
     (and (integer? height)
	  (not (< height 0))
	  (not (> height spine-levels))
	  (let ((temp-rib (nth height history)))
	    (set! current-reductions (rib-reductions temp-rib))
	    ;; Current branch doesn't have value
	    (set! current-branches (cdr (rib-subexpressions temp-rib)))
	    (set! current-height height)
	    (select-reduction 0)
	    height)))

   (define (select-reduction-loop)
     (princ "Reduction number (0 to ")
     (princ (- (length current-reductions) 1))
     (cond ((null? (select-reduction (read ") --> ")))
	    (display "That reduction doesn't exist")
	    (select-reduction-loop))
	   (else
	    *noprint*)))

   (define (select-reduction width)
     (and (integer? width)
	  (not (< width 0))
	  (< width current-reductions)
	  (sequence
	   (set! current-width width)
	   (set! current-reduction (nth current-width current-reductions))
	   (set! $ (unsyntax (reduction-expression current-reduction)))
	   width)))

   (define (go level reduction)
     (move level reduction "That reduction doesn't exist" t))

   (define (move he wi error-message display?)
     (cond ((null? (select-subproblem he))
	    (display error-message))
	   (else
	    (h-move wi error-message display?)
	    (if (= wi current-width) *noprint*
		(h-move 0 "Bad history" nil)))))

   (define (h-move wi error-message display?)
     (cond ((null? (select-reduction wi))
	    (display error-message))
	   ((null? display?)
	    *noprint*)
	   (else
	    (reduction))))
   
   ;;; Debugger system commands

   (define (info)                              ;command I
     (newline)
     (apply display error-info)
     (newline))

   (define (help)                              ;command ?
     (display help-message))

   (define (change-mode)                       ;command M
     (return-to-caller-of-driver *change-mode*))

   (define (exit-lazy)                         ;command Q
     (return-to-caller-of-driver *exit*))


   (define hist-commands
     (list (cons '? help)
	   (cons 'H all-history)
	   (cons 'A all-reductions)
           (cons 'Q exit-lazy)
	   (cons 'U next-subproblem)
	   (cons 'D previous-subproblem)
	   (cons 'F next-reduction)
	   (cons 'B previous-reduction)
	   (cons 'X subexpressions)
	   (cons 'I info)
	   (cons 'V eval-in-current-environment)
	   (cons 'E enter)
	   (cons 'S reduction)
	   (cons 'W debug-where)
	   (cons 'R return-lazy)
	   (cons 'M change-mode)
	   (cons 'G go-lazy)
	   (cons 'P print-procedure)))


   (define help-message "
U     Move up one subproblem level to <Next-subproblem>
D     Move down one subproblem level to <Previous-subproblem>
F     Move forward to <Next-reduction> on the same subproblem level
B     Move backwards to <Previous-reduction> on the same subproblem level
G     <Go> to subproblem and reduction desired

S     Show the current <Reduction> in short form
X     Show the <Subexpressions> of the last reduction at this level
P     <Print-procedure>, pretty-prints current procedure
A     <All-reductions>, display all the reductions at this level
H     <All-history>, display all the available history

V     <Eval-in-current-environment> an expression
E     <Enter>, enter a read-eval-print loop in the current environment
R     <Return>, evaluate an expression and proceed with it
W     <Debug-where>, display and manipulate the current environment

I     <Info>, repeat error message
M     <Toggle>, change debug mode
Q     <Exit> the debugger
?     <Help> prints this garbage")

   (define mode lazy-mode)))
))


scheme-system-package)